#include "stdafx.h"
#include "SDL.h"
#include "SDL_image.h"
#include "GlobalInfo.h"
#include "globalSDL.h"
#include "Entity.h"
#include "BoundsCheck.h"
#include "Grass.h"
#define INIT_FRAMES 4

//Flip flags
const int FLIP_VERTICAL = 1;
const int FLIP_HORIZONTAL = 2;

int m_nDirFrames[6];
CEntity::CEntity(void)
:m_nX(0),m_nY(0),m_nWidth(0),m_nHeight(0)
,m_nMVelocityX(0),m_nMVelocityY(0),m_nPVelocityX(0),m_nPVelocityY(0),
m_pFileDraw(0),m_pBound(0),m_bAnimate(false)
,m_nFrames(0),m_nCurFrames(0)
,m_bDirect(false)
{
	m_nDirFrames[0] = 4;
	m_nDirFrames[1] = 5;
	m_nDirFrames[2] = 6;
	m_nDirFrames[3] = 7;
	m_nDirFrames[4] = 6;
	m_nDirFrames[5] = 5;
}

CEntity::~CEntity(void)
{
	if( m_pFileDraw )
	{
		SDL_FreeSurface( m_pFileDraw );
	}
	if( m_pMirrorDraw )
	{
		SDL_FreeSurface( m_pMirrorDraw );
	}
}

void CEntity::CreateEntity( int x, int y, const std::string& strRes )
{
	bool bResult = false;
	//The image that's loaded
    SDL_Surface* loadedImage = NULL;

    //The optimized image that will be used
    SDL_Surface* optimizedImage = NULL;

    //Load the image using SDL_image
    loadedImage = IMG_Load( strRes.c_str() );

    //If the image loaded
    if( loadedImage != NULL )
    {
        //Create an optimized image
        m_pFileDraw = SDL_DisplayFormat( loadedImage );

        //Free the old image
        SDL_FreeSurface( loadedImage );
		bResult = true;
		
		SDL_Rect *rect = new SDL_Rect;
		SDL_GetClipRect(m_pFileDraw, rect);

		m_nWidth = rect->w;
		m_nHeight = rect->h;
		delete rect;

		SDL_SetColorKey( m_pFileDraw, SDL_SRCCOLORKEY, SDL_MapRGB( m_pFileDraw->format, 0x78, 0x78, 0x78 ) );
		m_pMirrorDraw = flip_surface( m_pFileDraw, FLIP_HORIZONTAL );
    }
	m_nX = x;
	m_nY = y;
}
void CEntity::SetMVelocity( int vx, int vy )
{
	m_nMVelocityX = vx;
	m_nMVelocityY = vy;
}
void CEntity::SetPVelocity( int vx, int vy )
{
	m_nPVelocityX = vx;
	m_nPVelocityY = vy;
}
void CEntity::OnDraw()
{
	SDL_Rect offset;

    //Get offsets
    offset.x = m_nX;
    offset.y = m_nY;
	
    //Blit the surface
	if( g_pSurface )
	{
		SDL_Rect animateRect;
		animateRect.x = 0;
		animateRect.y = 0;
		animateRect.w = 0;
		animateRect.h = 0;
		if( m_bAnimate )
		{
			int nIndex = 0;
			if( m_bDirect )
			{
				nIndex = 10 - m_nDirFrames[m_nCurFrames];
			}
			else 
			{
				nIndex = m_nDirFrames[m_nCurFrames];
			}
			animateRect.x = nIndex * 80;
			animateRect.y = 0;
			animateRect.w = 80;
			animateRect.h = 80;
			if( m_bDirect )
			{
				SDL_BlitSurface( m_pMirrorDraw, &animateRect, g_pSurface, &offset );
			}
			else
			{
				SDL_BlitSurface( m_pFileDraw, &animateRect, g_pSurface, &offset );
			}
		}
		else
		{
			SDL_BlitSurface( m_pFileDraw, NULL, g_pSurface, &offset );
		}
	}
}

void CEntity::EntityMove(Uint8 * keystates)
{
	int x = m_nX;
	int y = m_nY;
	x += m_nPVelocityX;
	y += m_nPVelocityY;
	int v = 4;
	if( m_nPVelocityY > 0 )
	{
		v = 1;
	}
	if( keystates[ SDLK_RIGHT ] )
	{
		x = m_nX + v;
		if( x > SCREEN_WIDTH )
		{
			x = 0;
		}
		m_nCurFrames++;
		m_bDirect = false;
	}
	if( keystates[ SDLK_LEFT ] )
	{
		x = m_nX - v;
		if( x + m_nWidth < 0 )
		{
			x = SCREEN_WIDTH;
		}
		m_nCurFrames++;
		m_bDirect = true;
	}
	if( m_nCurFrames >= m_nFrames )
	{
		m_nCurFrames = 0;
	}
	if( m_pBound )
	{
		if ( m_pBound->MoveAvailable( x, y, m_nWidth, m_nHeight ) )
		{
			m_nX = x;
			m_nY = y;
		}
	}
}
void CEntity::SetBounds( CBoundsCheck* pBounds )
{
	m_pBound = pBounds;
}
void CEntity::SetPos( int x, int y )
{
	m_nX = x;
	m_nY = y;
}
int CEntity::GetPVX() const
{
	return m_nPVelocityX;
}
int CEntity::GetPVY() const
{
	return m_nPVelocityY;
}
SDL_Rect CEntity::GetRect()
{
	SDL_Rect rect;
	rect.x = m_nX + 18;
	rect.y = m_nY;
	rect.w = m_nWidth - 18 * 2;
	rect.h = m_nHeight;
	return rect;
}
void CEntity::SetAnimate( bool bAni )
{
	m_bAnimate = bAni;
	m_nFrames = 6;
	m_nWidth = m_nWidth / 10;
	m_nHeight = m_nHeight / 7;
}

Uint32 CEntity::get_pixel32( SDL_Surface *surface, int x, int y )
{
	//Convert the pixels to 32 bit
    Uint32 *pixels = (Uint32 *)surface->pixels;

    //Get the requested pixel
    return pixels[ ( y * surface->w ) + x ];
}

void CEntity::put_pixel32( SDL_Surface *surface, int x, int y, Uint32 pixel )
{
	//Convert the pixels to 32 bit
    Uint32 *pixels = (Uint32 *)surface->pixels;

    //Set the pixel
    pixels[ ( y * surface->w ) + x ] = pixel;
}

SDL_Surface* CEntity::flip_surface( SDL_Surface *surface, int flags )
{
	    //Pointer to the soon to be flipped surface
    SDL_Surface *flipped = NULL;

    //If the image is color keyed
    if( surface->flags & SDL_SRCCOLORKEY )
    {
        flipped = SDL_CreateRGBSurface( SDL_SWSURFACE, surface->w, surface->h, surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, 0 );
    }
    //Otherwise
    else
    {
        flipped = SDL_CreateRGBSurface( SDL_SWSURFACE, surface->w, surface->h, surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, surface->format->Amask );
    }

    //If the surface must be locked
    if( SDL_MUSTLOCK( surface ) )
    {
        //Lock the surface
        SDL_LockSurface( surface );
    }

    //Go through columns
    for( int x = 0, rx = flipped->w - 1; x < flipped->w; x++, rx-- )
    {
        //Go through rows
        for( int y = 0, ry = flipped->h - 1; y < flipped->h; y++, ry-- )
        {
            //Get pixel
            Uint32 pixel = get_pixel32( surface, x, y );

            //Copy pixel
            if( ( flags & FLIP_VERTICAL ) && ( flags & FLIP_HORIZONTAL ) )
            {
                put_pixel32( flipped, rx, ry, pixel );
            }
            else if( flags & FLIP_HORIZONTAL )
            {
                put_pixel32( flipped, rx, y, pixel );
            }
            else if( flags & FLIP_VERTICAL )
            {
                put_pixel32( flipped, x, ry, pixel );
            }
        }
    }

    //Unlock surface
    if( SDL_MUSTLOCK( surface ) )
    {
        SDL_UnlockSurface( surface );
    }

    //Copy color key
    if( surface->flags & SDL_SRCCOLORKEY )
    {
        SDL_SetColorKey( flipped, SDL_RLEACCEL | SDL_SRCCOLORKEY, surface->format->colorkey );
    }

    //Return flipped surface
    return flipped;
}